/*
 * IndexedDictionaryWorker.java
 *
 * Copyright(c) 2010
 * Michael Kroez
 * kroez@studiorutton.de
 *
 * All rights reserved.
 *
 * $Id$
 * 
 */

package de.studiorutton.gerengdic.indexeddictionary;

import java.util.concurrent.atomic.AtomicBoolean;

import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import de.studiorutton.access.FileAccess;
import de.studiorutton.access.FileAccessException;
import de.studiorutton.access.FileLocation;
import de.studiorutton.gerengdic.databaseaccess.DatabaseAccess;
import de.studiorutton.gerengdic.databaseaccess.DatabaseAccessException;
import de.studiorutton.gerengdic.databaseaccess.LanguageAccess;
import de.studiorutton.gerengdic.databaseaccess.LanguageAccess.IndexPositionRange;

public class IndexedDictionaryWorker {
	private final static String TAG = "learningwords";
	private final FileLocation fileLocation;
	private HandlerThread searchThread;
	SearchMessageHandler handler;
	private DatabaseAccess dba;
	private AtomicBoolean isRunning;

	public static final int DONE_FULL = 0;
	public static final int DONE_CANCELLED = 1;
	public static final int DONE_ERROR = -1;

	private static final int SEARCH_CANCEL = 0;
	private static final int SEARCH_AUTOCOMPLETE_INFO = 1;

	private static final String REGEX_KEY = "regex";
	private static final String AMATCH_ENABLED = "amatch_enabled";

	public IndexedDictionaryWorker(FileLocation fileLocation)
			throws FileAccessException, DatabaseAccessException {

		this.fileLocation = fileLocation;
		FileAccess.checkExistsAndReadable(fileLocation);

		isRunning = new AtomicBoolean(false);
		startSearchThread();
	}

	public boolean getIsRunning() {
		return isRunning.get();
	}

	public DatabaseAccess getDatabaseAccess() {
		return dba;
	}

	public void startSearchThread() throws DatabaseAccessException,
			FileAccessException {
		// Log.d(TAG, "Starting new indexed dictionary thread.");
		dba = new DatabaseAccess(fileLocation.createFilePath());

		if (searchThread == null) {
			searchThread = new HandlerThread("Dictionary Thread");
			searchThread.start();
			Looper looper = searchThread.getLooper();
			handler = new SearchMessageHandler(looper);
		}
	}

	public void stopSearchThread() {
		if (searchThread != null)
			searchThread.interrupt();
		searchThread = null;
	}

	public void cancelSearchOperation() {
		Message msg = Message.obtain();
		msg.what = SEARCH_CANCEL;
		handler.removeMessages(SEARCH_AUTOCOMPLETE_INFO);
		handler.sendMessage(msg);
	}

	class SearchMessageHandler extends Handler {
		public SearchMessageHandler(Looper looper) {
			super(looper);
		}

		protected void finalize() {
			// Log.d(TAG, "stopping SearchMessageHandler");
		}

		public void handleMessage(Message msg) {
			// Log.d(TAG,
			// "handleMessage in worker thread called with msg.what = "
			// + msg.what + ".");
			// Do something with the message
			if (msg.what == SEARCH_CANCEL)
				return;

			IAutoCompleteListener acl = (IAutoCompleteListener) msg.obj;

			isRunning.set(true);
			if (acl != null)
				acl.notifyStart();

			int result = 0;
			switch (msg.what) {
			case SEARCH_AUTOCOMPLETE_INFO:
				result = executeSearchAutocompleteInfo(msg);
				break;
			}
			isRunning.set(false);
			if (acl != null)
				acl.notifyDone(result);
			return;
		}

		public int executeSearchAutocompleteInfo(Message msg) {
			IAutoCompleteListener acl = (IAutoCompleteListener) msg.obj;
			String searchString = msg.getData().getString(REGEX_KEY);
			boolean aMatchEnabled = msg.getData().getBoolean(AMATCH_ENABLED);
			int language = msg.arg1;

			LanguageAccess la = getDatabaseAccess().getContentAccess()
					.getLanguageAccess(language);

			IndexPositionRange ipr = la.getSuperIndexAccess().searchSuperIndex(
					searchString);
			try {
				la.getIndexPositionAccess().searchIndex(searchString,
						aMatchEnabled, ipr, acl);
			} catch (DatabaseAccessException e) {
				acl.notifyError(e.getLocalizedMessage());
				return DONE_ERROR;
			}

			return DONE_FULL;
		}
	}

	public void searchAutocompleteInfo(AutoCompleteHandler ach,
			String searchString, int language, boolean aMatchEnabled) {
		Bundle bundle = new Bundle();
		bundle.putString(REGEX_KEY, searchString);
		bundle.putBoolean(AMATCH_ENABLED, aMatchEnabled);

		Message msg = Message.obtain(handler);
		msg.what = SEARCH_AUTOCOMPLETE_INFO;
		msg.arg1 = language;
		msg.setData(bundle);
		msg.obj = ach;
		handler.sendMessage(msg);

	}

}
